<template>
  <PageableTable
    ref="table"
    class="sub-table"
    auto-height
    :data="rows"
    :api="fetchApi"
    :show-summary="showSummary"
    :selection-width="selectionWidth"
    v-bind="$attrs"
    hide-on-single-page
    :selection="enabled"
    v-on="$listeners"
    @selection-change="onSelectionChange">
    <template v-if="!editable" #toolbar>
      <div v-if="enabled || fetchApi" class="table-header">
        <slot name="toolbar" :add-row="addRow" :del-row="delRow" :refresh="refresh">
          <template v-if="enabled">
            <ElButton size="mini" class="table-header-button add" icon="el-icon-circle-plus" type="text" @click="addRow"> 添加 </ElButton>
            <ConfirmButton size="mini" class="table-header-button remove" message="您确定要删除选中的记录吗？" icon="el-icon-error" type="text" @click="delRow">
              删除
            </ConfirmButton>
          </template>
          <ElButton v-if="fetchApi" size="mini" class="table-header-button refresh" icon="el-icon-refresh-left" type="text" :disabled="false" @click="refresh">
            刷新
          </ElButton>
        </slot>
      </div>
    </template>
    <slot name="columns" :columns="columns">
      <template v-for="item in columns">
        <TableColumn
          v-if="item.label && !item.hide && !item.slot"
          :key="`${item.prop}-${enabled}-${item.type}`"
          :label="item.label"
          :width="item.width"
          :align="item.align"
          :prop="item.prop"
          :options="item.options"
          :show-overflow-tooltip="!available && item.showOverflowTooltip">
          <!--列头-->
          <template #header> <span v-if="!inputDisabled && item.required" style="color: #f56c6c">*</span>{{ item.label }} </template>
          <!--列内容-->
          <template #default="{ row, column, $index }">
            <!--tag 插槽-->
            <slot name="tag" :row="row" :column="column" :index="$index"></slot>
            <!--列默认插槽,名字和 prop 保持一致-->
            <slot :row="row" :column="column" :index="$index" :name="item.prop">
              <template v-if="available && getCellType(row, item) === 'input'">
                <FormInput
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'inputPhoneNumber'">
                <FormInputPhoneNumber
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'user'">
                <FormInputUser
                  v-if="item.single"
                  :is-user-check="isUserCheck"
                  :name.sync="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
                <FormInputUser
                  v-else
                  :is-user-check="isUserCheck"
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'department'">
                <FormInputDepartment
                  v-if="item.single"
                  :ou-type="item.ouType"
                  :name.sync="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
                <FormInputDepartment
                  v-else
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'select'">
                <FormSelect
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'datePicker'">
                <FormDatePicker
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  :start.sync="row[item.start]"
                  :end.sync="row[item.end]"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'cascader'">
                <FormCascader
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  :label-key="item.labelKey"
                  :value-key="item.valueKey"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'checkbox'">
                <FormCheckboxGroup
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="available && getCellType(row, item) === 'number'">
                <FormInputNumber
                  :value="row[column.property]"
                  v-bind="getInputAttr(row, item)"
                  :disabled="isInputDisabled(row, item)"
                  :prop="`${prop}[${$index}].${item.prop}`"
                  :required="item.required"
                  @input="val => onInput(row, val, item)" />
              </template>
              <template v-else-if="item.dicType || item.options?.length">
                <DictRender :dict-type="item.dicType" :column="column" :row="row" :options="item.options" />
              </template>
              <template v-else>{{ getVal(row, column, item) }}</template>
            </slot>
          </template>
        </TableColumn>
        <!--列自定义插槽,名字和 prop 不一致-->
        <slot v-else-if="item.slot"></slot>
      </template>
    </slot>
    <slot :add="add" :remove="remove" name="handle"></slot>
    <TableColumn
      v-if="(!value || value.length < limit) && !inputDisabled && enabled && editable && handleColumn"
      label="操作"
      fixed="right"
      width="80"
      align="center"
      prop="menu">
      <!--表头-->
      <template #header="{ column, $index }">
        <slot name="handle-column-header" :column="column" :index="$index">
          {{ column.label }}
        </slot>
      </template>
      <!--操作-->
      <template #default="{ row, $index }">
        <i
          v-if="showHandleColumnAddButton && value.length < maxLimit"
          class="el-icon-circle-plus sub-table-handle-button table-button-add"
          style="margin-right: 5px; font-size: 20px; cursor: pointer"
          title="添加"
          @click.stop="add(row, $index)"></i>
        <Confirmable
          v-if="(value && value.length > 1) || allowEmpty"
          class="el-icon-error sub-table-handle-button table-button-remove"
          title="删除"
          message="您确定要删除该行吗？"
          @click.stop="remove(row, $index)" />
      </template>
    </TableColumn>
    <!--底部添加按钮-->
    <template v-if="allowEmpty && !inputDisabled && showEmptyAddButton" #empty>
      <i
        class="el-icon-circle-plus sub-table-handle-button table-button-add"
        style="font-size: 20px; cursor: pointer"
        title="添加"
        @click.stop="add(null, 0)"></i>
    </template>
  </PageableTable>
</template>

<script>
  import { findTreeChildren, isFunction } from '@web-utils/core'
  import { cloneDeep } from '@web-utils/integrations/lodash'

  export default {
    name: 'SubTable',
    emits: ['add-row'],
    inject: {
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },
    props: {
      value: Array,
      prop: String,
      columns: Array,
      limit: {
        type: Number,
        default: Infinity
      },
      maxLimit: {
        type: Number,
        default: Infinity
      },
      disabled: Boolean,
      showSummary: Boolean,
      selectionWidth: String,
      allowEmpty: Boolean,
      handleColumn: {
        type: Boolean,
        default: true
      },
      editable: Boolean,
      fetchApi: Function,
      delApi: Function,
      showHandleColumnAddButton: {
        type: Boolean,
        default: true
      },
      showEmptyAddButton: {
        type: Boolean,
        default: true
      },
      isUserCheck: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        rows: [],
        selectedRows: []
      }
    },
    computed: {
      available() {
        return this.editable && this.enabled
      },
      enabled() {
        return !this.disabled
      },
      rowProps() {
        const props = {}
        if (!this.columns) {
          return props
        }
        this.columns
          .map(value => value.prop)
          .forEach(key => {
            props[key] = null
          })
        return props
      },
      inputDisabled() {
        return this.disabled || (this.elForm || {}).disabled
      }
    },
    watch: {
      value: {
        deep: true,
        immediate: true,
        handler(newVal) {
          this.rows = newVal || []
        }
      },
      rows: {
        deep: true,
        immediate: true,
        handler(newVal) {
          this.$emit('input', newVal)
        }
      }
    },
    methods: {
      getCellType(row, item) {
        if (isFunction(item.getType)) {
          return item.getType(row, item)
        } else {
          return item.type
        }
      },
      getInputAttr(row, item) {
        return { ...item.attrs, ...(item.getAttrs ? item.getAttrs(row) : {}) }
      },
      isInputDisabled(row, item) {
        return item.isDisabled && item.isDisabled(row)
      },
      onInput(row, val, item) {
        if (item.setValue) {
          item.setValue(row, val, item, this.rows)
        } else {
          row[item.prop] = val
        }
      },
      onSelectionChange(selectedRows) {
        this.selectedRows = selectedRows
      },
      async remove(row, index) {
        try {
          this.rows.splice(index, 1)
        } catch (e) {}
      },
      add(row, index) {
        const newRow = cloneDeep(this.rowProps)
        this.rows.splice(index + 1, 0, newRow)
      },
      addRow() {
        this.$emit('add-row')
      },
      async delRow() {
        if (!this.selectedRows.length) {
          this.$message.warning('请选择要删除的记录！')
          return
        }
        try {
          if (this.delApi) {
            try {
              await this.delApi(this.selectedRows.map(value => value.id).join(','))
              this.refresh()
            } catch (e) {
              this.$message.error('删除失败！')
            }
          } else {
            this.$emit(
              'input',
              this.rows.filter(value => !this.selectedRows.includes(value))
            )
          }
          this.$message.success('删除成功！')
        } catch (e) {}
      },
      refresh() {
        this.$refs.table.getPage()
      },
      getVal(row, column, item) {
        if (item.type === 'select' && item.attrs?.options) {
          const option = item.attrs.options.find(v => v.code === row[column.property])
          if (option) {
            return option.name
          }
        }

        if (item.type === 'cascader' && item.attrs?.options) {
          const [option] = findTreeChildren(item.attrs.options, node => node[item.attrs.valueKey || 'value'] === row[column.property])
          if (option) {
            return option[item.attrs.valueKey || 'label']
          }
        }

        return row[column.property]
      }
    }
  }
</script>

<style lang="scss">
  .sub-table {
    &.pageable-table.auto-height {
      .el-table {
        min-height: 0;
      }
    }

    .el-form-item {
      width: 100%;
      margin-bottom: 0;
    }

    .el-col {
      width: 100%;
    }

    .table-header {
      padding: 2px 10px;
      background-color: rgba(243, 245, 251, 1);
      border: 1px solid rgba(223, 230, 236, 1);
      border-bottom: none;
    }

    .table-header-button {
      &:hover,
      &:focus {
        color: #595959;
      }

      i + span {
        margin-left: 0;
      }

      i {
        font-size: 15px;
      }

      &.add {
        i {
          color: #4886ec;
        }
      }

      &.remove {
        i {
          color: #e34e55;
        }
      }

      &.refresh {
        i {
          color: #1eb91e;
        }
      }
    }

    .table-button-add {
      color: #5add7a;
      opacity: 0.8;

      &:hover {
        opacity: 1;
      }
    }

    .table-button-remove {
      color: #ddd;

      &:hover {
        color: #ef6666;
      }
    }

    .el-table__header-wrapper {
      .el-table__header {
        th {
          padding: 5px 0;
          background-color: rgba(243, 245, 251, 1);
        }
      }
    }

    .el-table {
      border-top-color: rgb(221, 225, 229);

      td {
        border-color: rgb(223, 230, 236);
      }
    }

    .el-col {
      padding: 0 !important;
    }

    .row-indicator {
      position: absolute;
      top: -6px;
      right: -6px;
      display: inline-block;
      width: 0;
      height: 0;
      border: 6px solid;
      border-color: transparent transparent #f5690c;
      transform: rotate(45deg);
    }

    .sub-table-handle-button {
      font-size: 20px;
      cursor: pointer;

      + .sub-table-handle-button {
        margin-left: 5px;
      }
    }

    .el-table .el-table__header th {
      padding: 5px 0;
      line-height: inherit;
      background: #f3f5fb !important;
    }
  }
</style>
